/* 
* Copyright (c) 2021 Talkweb Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. 
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "MQTTClient.h"
#include "wifi_connect.h"

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

// 默认WiFi名和密码
#define SELECT_WIFI_SSID "thinkgo"
#define SELECT_WIFI_PASSWORD "12345678"
#define SERVER_IP "tcp://192.168.137.1:1883"
#define SERVER_PORT 1883

static int MsgRcvCallBack(char *context, char *topic, int topicLen, MQTTClient_message *message)
{
    // message->payload[message->payloadlen]=0;
    printf("topic:%s, message: %s\r\n",topic,message->payload);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topic);
    return 1;
}

// < when the connect lost and this callback will be called
static void ConnLostCallBack(char *context, char *cause)
{
    printf("Connection lost:caused by:%s\r\n", cause == NULL? "Unknown" : cause);
    return;
}

int MqttDestory(int ret, MQTTClient client)
{
    if (ret != MQTTCLIENT_SUCCESS) {
        MQTTClient_destroy(&client);
        return -1;
    }
    return MQTTCLIENT_SUCCESS;
}


/**
 * @brief MQTT任务处理 
 * @param void
 * @return void
 */
static void MQTTDemoTask(void)
{
    int rc, count = 0;
    MQTTClient client;
    printf("Starting ...\n");

 begin:   
    // 连接WIFI
    printf("NetworkConnect  ...\n");
    rc = WifiConnect(SELECT_WIFI_SSID, SELECT_WIFI_PASSWORD);
    if(rc!=0){
        printf("WifiConnect FAIL\n");
        osDelay(100);
        goto begin;
    } 
    
    // 连接服务器网络
    printf("MQTTClient_create  ...\n");

     // 连接参数
    MQTTClient_connectOptions connOpts = MQTTClient_connectOptions_initializer;
    // 客户ID，唯一
    char *clientID = "thinkgo03";   
    // MQTT版本号
    connOpts.MQTTVersion = MQTTVERSION_3_1_1; 
    // 保存存活时间
    connOpts.keepAliveInterval = 50;
     // 重新连接后是否清除以前的信息 0表示不清除，1表示重连清除
    connOpts.cleansession = 1;
    // // 服务器用户名
    // connOpts.username = "user01";
    // // 服务器用户密码
    // connOpts.password = "123456";
    connOpts.connectTimeout = 60;
begin1:
    rc = MQTTClient_create(&client, SERVER_IP, clientID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
       printf("MQTTClient_create  FAIL\n");
        osDelay(100);
       goto begin1;
    }

    rc = MQTTClient_setCallbacks(client, NULL, ConnLostCallBack, MsgRcvCallBack, NULL);
    if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) {
        printf("MQTTClient_setCallbacks  FAIL\n");
         osDelay(100);
        goto begin1;
    }

    printf("MQTTClient_connect  ...\n");
    rc = MQTTClient_connect(client, &connOpts);
    
    if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) {
        printf("MQTTClient_connect  FAIL: %d\n",rc);
         osDelay(100);
        goto begin1;
    }

    printf("MQTTClient_connect  ok\n");

    rc = MQTTClient_subscribe(client,"test/b",2);
    if (MqttDestory(rc, client) != MQTTCLIENT_SUCCESS) {
        printf("MQTTClient_subscribe  FAIL\n");
        goto begin1;
    }
    MQTTClient_deliveryToken tocken;
    MQTTClient_message message;
    // 发布的内容
    char payload[] = {"{\"name\": \"thinkgo\",\"url\": \"https://www.thinkgo.site/\"}"};
    // 仅一次
    message.qos = 2;
    message.retained = 0;
    message.payload = payload;
    message.payloadlen = strlen(payload);
   while (++count)
    {
        // 发布
        rc = MQTTClient_publish(client, "test/a", message.payloadlen,message.payload,message.qos,message.retained, &tocken);
        if (rc != MQTTCLIENT_SUCCESS) {
            printf("MQTTClient_publish:failed\r\n");
            break;
        }
        rc = MQTTClient_waitForCompletion(client,&tocken,10000);
        if(rc!=0){
            printf("MQTTClient_waitForCompletion:failed\r\n");
        }
        osDelay(100);
    }
    printf("Connect success and Subscribe success\r\n");
    while (MQTTClient_isConnected(client)) {
        
        MQTTClient_yield();  // < make the keepalive done
    }

    MQTTClient_disconnect(client, 10000L);
    
}

// MQTTDemo教程
static void MQTTDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "MQTTDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    if (osThreadNew((osThreadFunc_t)MQTTDemoTask, NULL, &attr) == NULL)
    {
        printf("[MQTT_Demo] Failed to create MQTTDemoTask!\n");
    }
}

APP_FEATURE_INIT(MQTTDemo);